/*
 * Copyright (C) 2024 panpf <panpfpanpf@outlook.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.panpf.sketch.painter

import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import com.github.panpf.sketch.resize.Scale
import com.github.panpf.sketch.util.fromScale
import com.github.panpf.sketch.util.name

/**
 * Resize the [AnimatablePainter] to the specified size
 *
 * @see com.github.panpf.sketch.compose.core.common.test.painter.ResizeAnimatablePainterTest
 */
@Stable
class ResizeAnimatablePainter(
    painter: Painter,
    size: Size,
    contentScale: ContentScale = ContentScale.Crop,
    alignment: Alignment = Alignment.Center,
) : ResizePainter(painter, size, contentScale, alignment), AnimatablePainter {

    private val animatablePainter: AnimatablePainter

    @Deprecated(message = "Use ResizePainter(painter, size, contentScale, alignment) instead")
    constructor(
        painter: Painter,
        size: Size,
        scale: Scale,
    ) : this(
        painter = painter,
        size = size,
        contentScale = fromScale(scale).first,
        alignment = fromScale(scale).second
    )

    init {
        require(painter is AnimatablePainter) {
            "painter must be AnimatablePainter"
        }
        animatablePainter = painter
    }

    override fun start() {
        animatablePainter.start()
    }

    override fun stop() {
        animatablePainter.stop()
    }

    override fun isRunning(): Boolean {
        return animatablePainter.isRunning()
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other == null || this::class != other::class) return false
        other as ResizeAnimatablePainter
        if (painter != other.painter) return false
        if (size != other.size) return false
        if (contentScale != other.contentScale) return false
        return alignment == other.alignment
    }

    override fun hashCode(): Int {
        var result = painter.hashCode()
        // Because size are value classes, they will be replaced by long.
        // Long will lose precision when converting hashCode, causing the hashCode generated by different srcOffset and srcSize to be the same.
        result = 31 * result + size.toString().hashCode()
        result = 31 * result + contentScale.hashCode()
        result = 31 * result + alignment.hashCode()
        return result
    }

    override fun toString(): String = "ResizeAnimatablePainter(" +
            "painter=${painter.toLogString()}, " +
            "size=${size.width}x${size.height}, " +
            "contentScale=${contentScale.name}, " +
            "alignment=${alignment.name})"
}